﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;
using Signage01.dao;
using System.Windows.Media.Animation;
using Signage01.util;
using System.Windows.Threading;


namespace Signage01.rectangles
{
    public class RectangleResourceGraphics
    {
        private ResourceGraphics resource;
        private MainWindow mainWindow;
        private Channel channel;
        private bool dragged;
        private Canvas canvasContainer;

        private Rectangle _rectangle;
        ContextMenu contextMenu;

        // variables for rectangle resize and move
        UIElement source = null;
        bool captured = false;
        bool flagResize = false;
        enum Sides { Left, Right, None };
        Sides side = Sides.None;
        double initialResizeX;
        double finalResizeX;
        double initialMoveX;
        double finalMoveX;
        //

        DispatcherTimer timerUpdate;
        TextBlock textBlock;
        ResourceRSS resourceRSS;
        ResourceText resourceText;
        bool flagTextBlockAdded = false;

        public Rectangle Rectangle
        {
            get { return _rectangle; }
            set { _rectangle = value; }
        }

        public RectangleResourceGraphics(MainWindow mainWindow, ResourceGraphics resource, Channel channel, bool dragged)
        {
            textBlock = new TextBlock();
            this.mainWindow = mainWindow;
            this.resource = resource;
            this.channel = channel;
            this.dragged = dragged;
            this.canvasContainer = mainWindow.canvasTimeline;

            this.Rectangle = new Rectangle();

            this.Rectangle.Width = resource.Duration * 10;
            this.Rectangle.Height = mainWindow.channelVerticalLength;

            this.Rectangle.Stroke = Brushes.Black;
            this.Rectangle.StrokeThickness = 2;

            if (this.resource.GetType() == typeof(ResourceRSS))
            {
                this.resourceRSS = (ResourceRSS)resource;
            }
            else if (this.resource.GetType() == typeof(ResourceText))
            {
                this.resourceText = (ResourceText)resource;
            }
            
            if (dragged)
            {
                //Thread.Sleep(1000);
                int rectangleX = Convert.ToInt32(mainWindow.xDragRectangleTimeline);
                int rectangleY = Convert.ToInt32(Canvas.GetTop(mainWindow.rectangleResourceCurrent));
                Canvas.SetLeft(this.Rectangle, rectangleX);
                Canvas.SetTop(this.Rectangle, rectangleY);

                if (!checkIfInteractsWithOtherRectange2())
                {
                    setResourceThumbnail();
                    
                    this.canvasContainer.Children.Add(this.Rectangle);

                    addEvents();

                    // giving resource object duration based on image and video length, for image duration is 20,
                    // for video duration is equal to the video length

                    //
                    initializeContextMenu();
                    this.Rectangle.ContextMenu = contextMenu;
                    channel.ListResourceGraphics.Add(this.resource);
                    //Console.WriteLine("dragged true");                    

                }                
                else
                {
                    MessageBox.Show("You can't drop resource here, find another position!");
                }                
            }
            else
            {
                Canvas.SetLeft(this.Rectangle, resource.Offset * 10);
                Canvas.SetTop(this.Rectangle, mainWindow.resourceYPosition);

                setResourceThumbnail();

                this.canvasContainer.Children.Add(this.Rectangle);

                // adding the events for rectangle resize and move
                addEvents();

                // giving resource object duration based on image and video length, for image duration is 20,
                // for video duration is equal to the video length

                //
                initializeContextMenu();
                this.Rectangle.ContextMenu = contextMenu;
            }

        }

        private void initializeContextMenu()
        {
            contextMenu = new ContextMenu();

            MenuItem menuItemCopy = new MenuItem();
            menuItemCopy.Header = "Copy";
            menuItemCopy.Click += new RoutedEventHandler(menuItemCopyClick);

            MenuItem menuItemDelete = new MenuItem();
            menuItemDelete.Header = "Delete";
            menuItemDelete.Click += new RoutedEventHandler(menuItemDeleteClick);

            contextMenu.Items.Add(menuItemCopy);
            contextMenu.Items.Add(menuItemDelete);
        }

        private void addEvents()
        {
            this.Rectangle.AddHandler(Canvas.MouseLeftButtonDownEvent, new MouseButtonEventHandler(rectangle_MouseLeftButtonDown_1));
            this.Rectangle.AddHandler(Canvas.MouseLeftButtonUpEvent, new MouseButtonEventHandler(rectangle_MouseLeftButtonUp_1));
            this.Rectangle.AddHandler(Canvas.MouseMoveEvent, new MouseEventHandler(rectangle_MouseMove_1));
            this.Rectangle.AddHandler(Canvas.MouseLeaveEvent, new MouseEventHandler(rectangle_MouseLeave_1));
        }

        private void setResourceThumbnail()
        {
            ImageBrush uniformBrush = new ImageBrush();
            /*
            if(resource.TypeName.Equals("label"))
            {
                uniformBrush.ImageSource = new BitmapImage(new Uri(System.AppDomain.CurrentDomain.BaseDirectory + "icons\\ic_label_black_48dp.png", UriKind.Absolute));
                uniformBrush.Viewport = new Rect(0, 0, .3, 1);
            }
             */
            //else
            {

                uniformBrush.ImageSource = new BitmapImage(new Uri(System.AppDomain.CurrentDomain.BaseDirectory + "icons\\rss-square.jpg", UriKind.Absolute));
                //uniformBrush.Stretch = Stretch.None;
                uniformBrush.Viewport = new Rect(0, 0, .3, 1);

            }
            
            uniformBrush.TileMode = TileMode.None;

            this.Rectangle.Fill = uniformBrush;
        }

        private void menuItemCopyClick(Object sender, RoutedEventArgs e)
        {
            Console.WriteLine("copy clicked");
        }

        private void menuItemDeleteClick(Object sender, RoutedEventArgs e)
        {
            
            //mainWindow.rectangleResourceSelected = this;
            Console.WriteLine("delete clicked");

            MessageBoxResult messageBoxResult = System.Windows.MessageBox.Show("Are you sure?", "Resource Delete Confirmation", System.Windows.MessageBoxButton.YesNo);
            if (messageBoxResult == MessageBoxResult.Yes)
            {
                this.channel.ListResourceGraphics.Remove(this.resource);
                mainWindow.listviewTimeline_SelectionChanged_1(null, null);

                CampaignDAO campaignDAO = CampaignDAO.getSingleTon();
                campaignDAO.updateCampaign(mainWindow.campaignSelected);
            }
             
        }

        

        private void rectangle_MouseLeftButtonDown_1(object sender, MouseButtonEventArgs e)
        {
            mainWindow.rectangleResourceGraphicsSelected = this;
            //Console.WriteLine("selected resource: " + mainWindow.rectangleResourceSelected.Resource.LocalFile.FileName);
            //mainWindow.flagCamapaignOn = false;
            //showAssociatedPropertyGrid();
            showResourceinCanvasCampaign();

            source = (UIElement)sender;
            Mouse.Capture(source);
            captured = true;
            this.Rectangle.Stroke = Brushes.Orange;

            initialMoveX = Canvas.GetLeft(this.Rectangle);
            finalMoveX = e.GetPosition(canvasContainer).X;

            mainWindow.Cursor = Cursors.Hand;
            
            if (flagResize)
            {
                initialResizeX = Canvas.GetLeft(this.Rectangle);
            }
        }

        private void showResourceinCanvasCampaign()
        {
            if (dragged)
            {
                if (resourceRSS.StrAllNewsTitles.Equals(""))
                {
                    MessageBox.Show("RSS feed is not ready yet!");
                    return;
                }
                else
                {
                    timerUpdate = new DispatcherTimer();
                    timerUpdate.Interval = TimeSpan.FromSeconds(0);
                    timerUpdate.Tick += updateRSStitles;
                    timerUpdate.IsEnabled = true;
                }
            }
            else
            {
                timerUpdate = new DispatcherTimer();
                timerUpdate.Interval = TimeSpan.FromSeconds(0);
                timerUpdate.Tick += updateRSStitles;
                timerUpdate.IsEnabled = true;
            }
            mainWindow.campaignCanvas.Children.Clear();
            /*
            Canvas canvasInner = new Canvas();

            Canvas.SetLeft(canvasInner, 30);
            Canvas.SetTop(canvasInner, 30);
            canvasInner.ClipToBounds = true;
            canvasInner.Background = Brushes.Aqua;
            canvasInner.Width = 400;
            canvasInner.Height = 40;
            */
            mainWindow.campaignCanvas.ClipToBounds = true;
            //mainWindow.campaignCanvas.Children.Add(canvasInner);
            /*
            TextBlock textBlock = new TextBlock();
            ResourceRSS resourceRSS = (ResourceRSS)resource;
            string str = resourceRSS.StrAllNewsTitles;
            textBlock.Text = str ;
            textBlock.FontSize = 20;

            textBlock.TextWrapping = TextWrapping.WrapWithOverflow;
                
            //textBlock.Margin

            //canvasInner.Children.Add(textBlock);
            mainWindow.campaignCanvas.Children.Add(textBlock);

            DoubleAnimation doubleAnimation = new DoubleAnimation();
            doubleAnimation.From = -textBlock.ActualWidth;
            doubleAnimation.To = mainWindow.campaignCanvas.ActualWidth;
            doubleAnimation.RepeatBehavior = RepeatBehavior.Forever;
            doubleAnimation.Duration = new Duration(TimeSpan.FromSeconds(20));
            //textBlock.BeginAnimation(Canvas.LeftProperty, doubleAnimation);

            
            
            mainWindow.storyBoardCampaignCanvas = new Storyboard();
            mainWindow.storyBoardCampaignCanvas.Children.Add(doubleAnimation);
            Storyboard.SetTarget(doubleAnimation, textBlock);
            Storyboard.SetTargetProperty(doubleAnimation, new PropertyPath("(Canvas.Right)"));
            mainWindow.storyBoardCampaignCanvas.Begin();
            */
            
            //resourceRSS = (ResourceRSS)resource;
            //string str = resourceRSS.StrAllNewsTitles;
            //textBlock.Text = str;
            showMessageUsingStoryboard();
        }

        private void showMessageUsingStoryboard()
        {
            double textBoxWidth;
            
            textBlock.Text = resourceRSS.StrAllNewsTitles;
            textBlock.FontSize = 20;
            textBlock.FontWeight = (resourceRSS.IsBold == true) ? FontWeights.Bold : FontWeights.Normal;
            textBlock.TextDecorations = (resourceRSS.IsUnderlined == true) ? TextDecorations.Underline : null;
            textBlock.FontStyle = (resourceRSS.IsItalic == true) ? FontStyles.Italic : FontStyles.Normal;
            if (resourceRSS.TextColor == null)
            {
                resourceRSS.TextColor = new ColorCustom();
            }

            textBlock.Foreground = new SolidColorBrush(Color.FromRgb(Convert.ToByte(resourceRSS.TextColor.Red), Convert.ToByte(resourceRSS.TextColor.Green), Convert.ToByte(resourceRSS.TextColor.Blue)));
            if (resourceRSS.FontFamily == null)
            {
                resourceRSS.FontFamily = "Arial";
            }
            textBlock.FontFamily = new System.Windows.Media.FontFamily(resourceRSS.FontFamily);
            //

            //
            double pixelXFactor;
            double canvaswidth = mainWindow.campaignCanvas.Width;
            double negXOffSet = 0;
            double fromSecValue = 0;            
            double equSlope = 0.022546419;
            double offSetY = 10.96286472;
            double stringSize;

            int textLen = resourceRSS.StrAllNewsTitles.Length;


            //Set the width of the text box according to the width (not length) of the text in it.  

            System.Globalization.CultureInfo enUsCultureInfo;
            Typeface fontTF;
            FormattedText frmmtText;

            if (textLen > 0)
            {
                enUsCultureInfo = System.Globalization.CultureInfo.GetCultureInfo("en-us");
                fontTF = new Typeface(textBlock.FontFamily, textBlock.FontStyle, textBlock.FontWeight, textBlock.FontStretch);
                frmmtText = new FormattedText(resourceRSS.StrAllNewsTitles, enUsCultureInfo, FlowDirection.LeftToRight, fontTF, textBlock.FontSize, textBlock.Foreground);

                stringSize = frmmtText.Width;


                if (stringSize < 100)
                    pixelXFactor = 1.02;
                else
                    pixelXFactor = 1.01;

                textBoxWidth = stringSize * pixelXFactor;

                textBlock.Width = textBoxWidth;
                negXOffSet = textBoxWidth * -1;

                fromSecValue = (stringSize * equSlope) + offSetY;

                if (flagTextBlockAdded == false)
                {
                    mainWindow.campaignCanvas.Children.Add(textBlock); //rectangle
                    flagTextBlockAdded = true;
                }
                mainWindow.storyBoardCampaignCanvas = new Storyboard();

                Duration durX = new Duration(TimeSpan.FromSeconds(fromSecValue));

                DoubleAnimation daX = new DoubleAnimation(canvaswidth, negXOffSet, durX);
                daX.RepeatBehavior = RepeatBehavior.Forever;

                Storyboard.SetTarget(daX, textBlock);
                string strDirection = "";
                if (resourceRSS.DirectionText == EnumAll.DirectionText.LEFT_TO_RIGHT)
                {
                    strDirection = "Canvas.Right";
                }
                else
                {
                    strDirection = "Canvas.Left";
                }
                Console.WriteLine("str direction: " + strDirection);
                Storyboard.SetTargetProperty(daX, new PropertyPath("(" + strDirection + ")"));

                //Storyboard.SetTargetName(daX, "rtTTransform");
                //Storyboard.SetTargetProperty(daX, new PropertyPath(TranslateTransform.XProperty));

                mainWindow.storyBoardCampaignCanvas.Children.Add(daX);
                mainWindow.storyBoardCampaignCanvas.Begin(textBlock);
            }
        }


        private void updateRSStitles(object sender, EventArgs e)
        {
            resourceRSS.StrAllNewsTitles = RssUtil.getAllTitlesCombined(resourceRSS.RssSource);
            string strRSS = resourceRSS.StrAllNewsTitles;
            if (strRSS.Equals(""))
            {
                timerUpdate.Interval = TimeSpan.FromSeconds(1 * 5);
                Console.WriteLine("RSS not ready yet!");
            }
            else
            {
                textBlock.Text = strRSS;
                Console.WriteLine("RSS ready!"); 
                showMessageUsingStoryboard();
                timerUpdate.Interval = TimeSpan.FromSeconds(30 * 60); // 30 mins                
                Console.WriteLine(strRSS);
            }
        }

        private void rectangle_MouseLeftButtonUp_1(object sender, MouseButtonEventArgs e)
        {
            if (e.ClickCount == 2)
            {
                Console.WriteLine("double clicked");
                return;
            }
            this.Rectangle.Stroke = Brushes.Black;
            captured = false;
            Mouse.Capture(null);
            mainWindow.Cursor = Cursors.Arrow;

            resource.Offset = Convert.ToInt32(Canvas.GetLeft(this.Rectangle) / 10);
            resource.Duration = Convert.ToInt32(this.Rectangle.Width / 10);

            CampaignDAO campaignDAO = CampaignDAO.getSingleTon();
            campaignDAO.updateCampaign(mainWindow.campaignSelected);


            //mainWindow.spinnerResourceDuration.Value = TimeSpan.FromSeconds(resource.Duration);
            //mainWindow.spinnerResourceOffset.Value = TimeSpan.FromSeconds(resource.Offset);
        }

        private void rectangle_MouseLeave_1(object sender, MouseEventArgs e)
        {
            
            if (captured == false)
            {
                flagResize = false;
            }
            mainWindow.Cursor = Cursors.Arrow;
        }

        private void rectangle_MouseMove_1(object sender, MouseEventArgs e)
        {            
            if (captured)
            {
                // first rectangleon canvas change
                double finalNewMoveX = e.GetPosition(canvasContainer).X;


                double newX = initialMoveX + (finalNewMoveX - finalMoveX);
                
                initialMoveX = newX;
                finalMoveX = finalNewMoveX;
                
                if (!checkIfInteractsWithOtherRectange() && initialMoveX >= 0)
                {
                    Canvas.SetLeft(this.Rectangle, Convert.ToDouble(initialMoveX));
                }
            }

            if (checkIfMouseOnRectangleEdge(e))
            {
                mainWindow.Cursor = Cursors.SizeWE;
                flagResize = true;
            }
            else
            {
                mainWindow.Cursor = Cursors.Arrow;
                flagResize = false;
            }

            if (flagResize && captured)
            {
                if (side == Sides.Left)
                {
                    double finalNewResizeX = e.GetPosition(canvasContainer).X;

                    double newX = finalNewResizeX;

                    Console.WriteLine("Resize new x: " + newX);

                    
                    if (!checkIfInteractsWithOtherRectange())
                    {
                        Canvas.SetLeft(this.Rectangle, newX);
                        this.Rectangle.Width = initialResizeX - finalNewResizeX + this.Rectangle.Width;

                        //y_canvas = y;

                        initialResizeX = newX;

                        finalResizeX = finalNewResizeX;
                    }
                }
                else if (side == Sides.Right)
                {
                    double finalNewResizeX = e.GetPosition(canvasContainer).X;

                    double newX = initialResizeX;


                    if (!checkIfInteractsWithOtherRectange())
                    {
                        Canvas.SetLeft(this.Rectangle, newX);

                        this.Rectangle.Width = finalNewResizeX - initialResizeX;


                        initialResizeX = newX;
                        finalResizeX = finalNewResizeX;
                    }

                }

            }
        }

        // this check is required during rectangle move, resize
        private bool checkIfInteractsWithOtherRectange()
        {
            // first checking with image/video rectangles
            foreach (Resource resourceTemp in channel.ListResource)
            {                
                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(initialMoveX, Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }

            foreach (ResourceGraphics resourceGraphicsTemp in channel.ListResourceGraphics)
            {
                if (resourceGraphicsTemp == this.resource)
                {
                    continue;
                }

                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(initialMoveX, Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceGraphicsTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceGraphicsTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }

            return false;
        }


        // this check is required during dragging a graphics element, i.e. RSS, Text
        private bool checkIfInteractsWithOtherRectange2()
        {
            foreach (Resource resourceTemp in channel.ListResource)
            {
                /*
                if (resourceTemp == this.resource)
                {
                    continue;
                }
                */
                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(Canvas.GetLeft(this.Rectangle), Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }

            foreach (ResourceGraphics resourceGraphicsTemp in channel.ListResourceGraphics)
            {

                if (resourceGraphicsTemp == this.resource)
                {
                    continue;
                }
                
                //Rect rectThis = new Rect(initialMoveX,Canvas.GetTop(this.Rectangle),resource.Duration*10,30);
                Rect rectThis = new Rect(Canvas.GetLeft(this.Rectangle), Canvas.GetTop(this.Rectangle), resource.Duration * 10, mainWindow.channelVerticalLength);

                //Rect rectOther = new Rect(resourceTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceTemp.Duration * 10, 30);
                Rect rectOther = new Rect(resourceGraphicsTemp.Offset * 10, Canvas.GetTop(this.Rectangle), resourceGraphicsTemp.Duration * 10, mainWindow.channelVerticalLength);

                if (rectThis.IntersectsWith(rectOther))
                {
                    return true;
                }
            }

            return false;
        }


        private bool checkIfMouseOnRectangleEdge(MouseEventArgs e)
        {
            // we have to work here only on left and right edge
            double mousePositionX = e.GetPosition(this.Rectangle).X;
            double mousePositionY = e.GetPosition(this.Rectangle).Y;

            double rectangleYTop = Canvas.GetTop(this.Rectangle);
            double rectangleYBottom = Canvas.GetTop(this.Rectangle) + mainWindow.channelVerticalLength;

            //Console.WriteLine(mousePositionX + "," + mousePositionY + "," + rectangleYTop + "," + rectangleYBottom);
            //
            // mouse is near the left edge of the rectangle
            if (mousePositionX < 5 && mousePositionY >= 5 && mousePositionY <= this.Rectangle.Width)
            {
                side = Sides.Left;
                return true;
            }

            // mouse is near the right edge of the rectangle
            else if (mousePositionX <= this.Rectangle.Width && mousePositionX >= this.Rectangle.Width - 5 && mousePositionY >= 5 && mousePositionY <= this.Rectangle.Width)
            {
                side = Sides.Right;
                return true;
            }
            else
            {
                return false;
            }
        }// end checkif mouse on rectanlge edge

      
    }
}
